﻿
namespace Patterns4Net.Core.CecilExtensions.CILPatternsMatching
{
    using System.Diagnostics.Contracts;
    using Mono.Cecil.Cil;

    /// <summary>
    /// Matches given sequence of instructions which may be any preceded and followed by any other instructions sequence.
    /// </summary>
    public sealed class FreeFormInstructionMatcher : InstructionMatcher
    {
        private readonly CILPatternsMatcher inertnalMatcher;

        public FreeFormInstructionMatcher(InstructionMatcher nextMatcher)
        {
            Contract.Requires(nextMatcher != null);
            Contract.Ensures(this.inertnalMatcher != null);
            this.inertnalMatcher = new CILPatternsMatcher(nextMatcher);
        }

        public FreeFormInstructionMatcher(CILPatternsMatcher nextMatcher)
        {
            Contract.Requires(nextMatcher != null);
            Contract.Ensures(this.inertnalMatcher == nextMatcher);
            this.inertnalMatcher = nextMatcher;
        }

        public override bool Matches(Instruction instruction, out Instruction next)
        {
            Instruction nextFromInternalMatcher;
            if (this.inertnalMatcher.Matches(instruction, out nextFromInternalMatcher))
            {
                this.Found = true;
                next = nextFromInternalMatcher;
                return true;
            }

            /* There could be some logic for jump/branch instructions, 
               but at the moment they are not supported. */
            next = instruction.Next;
            return true;
        }
    }
}
